﻿#define _CRT_SECURE_NO_WARNINGS 1

//sizeof操作符
int main()
{
	int a = 0;
	printf("%zd\n", sizeof(a));
	printf("%zd\n", sizeof a);//证明了sizeof不是函数

	printf("%zd\n", sizeof(int));

	return 0;
}

//strlen函数
#include<string.h>
int main()
{
	size_t len = strlen("abc\0def");
	printf("%zd\n", len);

	//const char* str = "abcdef";
	char str[] = "abcdef";
	printf("%zd\n", strlen(str));

	char arr[] = { 'a','b','c' };
	printf("%zd\n", strlen(arr));//随机值


	return 0;
}

int main()
{
	int a = 8;
	short s = 4;
	printf("%zd\n", sizeof(s = a + 2));//2+
	printf("%d\n", s);//4

	return 0;
}

//数组和指针笔试题解析
// 
//1 ⼀维数组
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16 - sizeof(数组名)
	printf("%d\n", sizeof(a + 0));//4/8 - a是首元素的地址-类型是int*，a+0还是首元素的地址，是地址大小就是4/8
	printf("%d\n", sizeof(*a));//4 - *a就是首元素
	//*a = a[0] = *(a+0)
	printf("%d\n", sizeof(a + 1));//4/8 - a是首元素地址-类型是int*，a+1是第二个元素的地址
	printf("%d\n", sizeof(a[1]));//4 - a[1]就是第二个元素2
	printf("%d\n", sizeof(&a));//4/8 - &a是数组的地址，数组的地址也是地址，类型为int(*)[4]
	printf("%d\n", sizeof(*&a));//16 - *&相互抵消或对数组指针解引用
	printf("%d\n", sizeof(&a + 1));//4/8 - &a+1是跳过数组后的地址，也是地址，类型为int(*)[4]
	printf("%d\n", sizeof(&a[0]));//4/8 - 首元素的地址，还是地址
	printf("%d\n", sizeof(&a[0] + 1));//4/8 - 数组第二个元素的地址

	return 0;
}



//2 字符数组
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6 - arr表示整个数组，计算数组的大小
	printf("%d\n", sizeof(arr + 0));//4/8 - arr是数组名，首元素的地址，arr+0还是首元素地址
	printf("%d\n", sizeof(*arr));//1 - 首元素，大小一个字节
	printf("%d\n", sizeof(arr[1]));//1 - 第二个元素，大小一个字节
	printf("%d\n", sizeof(&arr));//4/8 - 整个数组的地址，类型为char(*)[6]
	printf("%d\n", sizeof(&arr + 1));//4/8 - &arr+1是跳过数组后的地址，也是地址，类型为char(*)[6]
	printf("%d\n", sizeof(&arr[0] + 1));//4/8 - 第二个元素的地址，也是地址

	return 0;
}

#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//随机值 - arr表示整首元素的地址，数组中没有\0，越界访问
	printf("%d\n", strlen(arr + 0));//随机值 - arr+0是数组首元素的地址，数组中没有\0，越界访问
	printf("%d\n", strlen(*arr));//error - 首元素，就是'a'，a的ASCII码值为97，相当于97传给strlen，得到的就是野指针
	//size_t strlen(const char* s)
	printf("%d\n", strlen(arr[1]));//error- 第二个元素，ASCII码值为98，相当于98传给strlen，得到的就是野指针
	printf("%d\n", strlen(&arr));//随机值 - &arr是数组的地址，起始位置是数组的第一个元素
	printf("%d\n", strlen(&arr + 1));//随机值 - &arr+1是跳过数组后的地址
	printf("%d\n", strlen(&arr[0] + 1));//随机值 - 第二个元素后到\0

	return 0;
}

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7 - arr是数组名，单独放在sizeof内部，计算数组大小
	printf("%d\n", sizeof(arr + 0));//4/8 - arr+0还是表示数组首元素的地址
	printf("%d\n", sizeof(*arr));//1 - *arr表示数组第一个元素
	printf("%d\n", sizeof(arr[1]));//1 - arr[1]表示数组的第二个元素
	printf("%d\n", sizeof(&arr));//4/8 - 整个数组的地址
	printf("%d\n", sizeof(&arr + 1));//4/8 - 跳过数组后的地址，也是地址
	printf("%d\n", sizeof(&arr[0] + 1));//4/8 - 第二个元素的地址，也是地址

	return 0;
}

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6 - 统计arr到\0元素的个数
	printf("%d\n", strlen(arr + 0));//6 - arr+0还是表示数组首元素的地址，向后在\0之前有6个字符
	printf("%d\n", strlen(*arr));//error - *arr表示数组第一个元素'a'，ASCII码值为97，相当于97传给strlen，得到的就是野指针
	printf("%d\n", strlen(arr[1]));//error - 第二个元素，ASCII码值为98，相当于98传给strlen，得到的就是野指针
	printf("%d\n", strlen(&arr));//6 - &arr是数组的地址，起始位置是数组的第一个元素，也是从第一个元素开始向后找
	printf("%d\n", strlen(&arr + 1));//随机值 - 跳过数组后的地址
	printf("%d\n", strlen(&arr[0] + 1));//5 - 第二个元素的地址，从第二个元素开始向后找

	return 0;
}

int main()
{
	const char* p = "abcdef";
	printf("%d\n", sizeof(p));//4/8 - p是指针变量，计算指针变量的大小
	printf("%d\n", sizeof(p + 1));//4/8 - - p+1表示数组第二个元素的地址，向后在\0之前有5个字符
	printf("%d\n", sizeof(*p));//1 - *p表示数组第一个元素
	printf("%d\n", sizeof(p[0]));//1 - 表示第一个元素，就是'a'
	printf("%d\n", sizeof(&p));//4/8 - 取出的是p的地址
	printf("%d\n", sizeof(&p + 1));//4/8 - &p+1是跳过p指针变量的大小后的地址
	printf("%d\n", sizeof(&p[0] + 1));//4/8 - 第二个元素的地址

	return 0;
}

int main()
{
	const char* p = "abcdef";
	printf("%d\n", strlen(p));//6 - 统计p到\0元素的个数
	printf("%d\n", strlen(p + 1));//5 - p+1是b的地址
	printf("%d\n", strlen(*p));//error - p的类型是const char*，*p就是char类型了
	printf("%d\n", strlen(p[0]));//error - 表示数组第一个元素'a'，ASCII码值为97，相当于97传给strlen，得到的就是野指针
	printf("%d\n", strlen(&p));//随机值 - 指针变量的地址，和常量字符串关系不大
	printf("%d\n", strlen(&p + 1));//随机值 - 指针变量的地址+1
	printf("%d\n", strlen(&p[0] + 1));//5 - 第二个元素的地址

	return 0;
}



//3.二维数组
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48 - a是数组名，单独放在sizeof内部，计算数组的大小
	printf("%d\n", sizeof(a[0][0]));//4 - 数组的第一个元素
	printf("%d\n", sizeof(a[0]));//16 - 第一行的数组a[0][1]、a[0][2]、a[0][3]
	printf("%d\n", sizeof(a[0] + 1));//4/8 - a[0]并没有单独放在sizeof内部，表示数组首元素的地址，a[0]+1表示a[0][1]的地址
	printf("%d\n", sizeof(*(a[0] + 1)));//4 - 表示a[0][1]
	printf("%d\n", sizeof(a + 1));//4/8 - a表示二维数组数组首元素的地址，也就是第一行的地址，所以a+1是第二行地址，a+1是数组指针
	printf("%d\n", sizeof(*(a + 1)));//16 - 第二行的大小
	printf("%d\n", sizeof(&a[0] + 1));//4/8 - 第二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//16 - 对第二行的地址解引用
	printf("%d\n", sizeof(*a));//16 - *a就是第一行，计算的是第一行的大小
	printf("%d\n", sizeof(a[3]));//16 - a[3]表示数组第四行，无需真实存在，仅仅通过类型推断就能算出长度

	return 0;
}


//指针运算笔试题解析

int main()
{
	int a[5] = { 1,2,3,4,5 };
	int* ptr = (int*)(&a + 1);
	printf("%d %d", *(a + 1), *(ptr - 1));//2 5

	return 0;
}


//在X86环境下
//假设结构体的大小是20个字节
//程序输出的结果是啥?
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;

//指针+-整数
//
int main()
{
	 printf("%p\n", p + 0x1);//0x100014
	 printf("%p\n", (unsigned long)p + 0x1);//0x100001 - 整型+1,就是+1
	 printf("%p\n", (unsigned int*)p + 0x1); //0x100004

	 return 0;
}


#include <stdio.h>

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);//1

	return 0;
}